package com.kds.smarthome.controller;

import com.kds.smarthome.annotation.Log;
import com.kds.smarthome.common.AjaxResponse;
import com.kds.smarthome.common.PageResult;
import com.kds.smarthome.entity.Building;
import com.kds.smarthome.entity.LoginInfo;
import com.kds.smarthome.entity.User;
import com.kds.smarthome.service.LoginInfoService;
import com.kds.smarthome.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author 孔德嵩
 * 创建日期 2024/12/3
 */
@Slf4j
@RestController
@RequestMapping("/api/users")
public class UserController {

    @Autowired
    private UserService userService;

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Autowired
    private LoginInfoService loginInfoService;

    private static final String USER_BUILDINGS_CACHE_KEY = "user:buildings:";

    /**
     * 清除用户建筑缓存
     */
    private void clearUserBuildingsCache(String username) {
        String key = USER_BUILDINGS_CACHE_KEY + username;
        redisTemplate.delete(key);
        log.debug("Cleared building cache for user: {}", username);
    }

    @Log(title = "用户管理", businessType = 0)
    @GetMapping
    @PreAuthorize("hasRole('ADMIN')")
    public AjaxResponse<PageResult<User>> getList(
            @RequestParam(required = false) String username,
            @RequestParam(required = false) Boolean enabled,
            @RequestParam(defaultValue = "1") Integer pageNum,
            @RequestParam(defaultValue = "10") Integer pageSize) {

        Map<String, Object> params = new HashMap<>();
        params.put("username", username);
        params.put("enabled", enabled);
        params.put("offset", (pageNum - 1) * pageSize);
        params.put("limit", pageSize);

        List<User> users = userService.findAll(params);
        long total = userService.count(params);

        return AjaxResponse.success(new PageResult<>(users, total));
    }

    @Log(title = "查询用户详情", businessType = 0)
    @GetMapping("/{id}")
    @PreAuthorize("hasRole('ADMIN')")
    public AjaxResponse<User> getDetail(@PathVariable Long id) {
        User user = userService.findById(id);
        return AjaxResponse.success(user);
    }

    @Log(title = "创建用户", businessType = 1)
    @PostMapping
    @PreAuthorize("hasRole('ADMIN')")
    public AjaxResponse<?> create(@RequestBody User user) {
        // 确保提供了密码
        if (user.getPassword() == null || user.getPassword().isEmpty()) {
            return AjaxResponse.error("创建用户时必须提供密码");
        }

        try {
            userService.createUser(user);
            return AjaxResponse.success("创建用户成功");
        } catch (RuntimeException e) {
            if (e.getMessage().contains("用户名已存在")) {
                return AjaxResponse.error("用户名已存在，请使用其他用户名");
            }
            return AjaxResponse.error("创建用户失败：" + e.getMessage());
        }
    }

    @Log(title = "更新用户", businessType = 2)
    @PutMapping("/{id}")
    @PreAuthorize("hasRole('ADMIN')")
    public AjaxResponse<?> update(@PathVariable Long id, @RequestBody User user) {
        user.setId(id);
        userService.updateUser(user);
        return AjaxResponse.success("更新用户成功");
    }

    @Log(title = "删除用户", businessType = 3)
    @DeleteMapping("/{id}")
    @PreAuthorize("hasRole('ADMIN')")
    public AjaxResponse<?> delete(@PathVariable Long id) {
        userService.deleteUser(id);
        return AjaxResponse.success("删除用户成功");
    }

    @Log(title = "批量删除用户", businessType = 3)
    @DeleteMapping("/batch")
    @PreAuthorize("hasRole('ADMIN')")
    public AjaxResponse<?> batchDelete(@RequestBody Map<String, List<Long>> payload) {
        userService.deleteUsers(payload.get("ids"));
        return AjaxResponse.success("批量删除用户成功");
    }

    @Log(title = "获取用户信息", businessType = 0)
    @GetMapping("/info")
    public AjaxResponse<User> getUserInfo(@RequestParam String username) {
        User user = userService.findByUsername(username);
        return AjaxResponse.success(user);
    }

    @Log(title = "修改用户密码", businessType = 2)
    @PutMapping("/{id}/password")
    @PreAuthorize("hasRole('ADMIN')")
    public AjaxResponse<?> updatePassword(@PathVariable Long id, @RequestBody Map<String, String> payload) {
        String oldPassword = payload.get("oldPassword");
        String newPassword = payload.get("newPassword");

        // 参数校验
        if (oldPassword == null || oldPassword.trim().isEmpty()) {
            return AjaxResponse.error("旧密码不能为空");
        }
        if (newPassword == null || newPassword.trim().isEmpty()) {
            return AjaxResponse.error("新密码不能为空");
        }

        try {
            userService.updatePassword(id, oldPassword, newPassword);
            return AjaxResponse.success("修改密码成功");
        } catch (RuntimeException e) {
            return AjaxResponse.error(e.getMessage());
        }
    }

    @Log(title = "锁定/解锁用户", businessType = 2)
    @PutMapping("/{id}/lock")
    @PreAuthorize("hasRole('ADMIN')")
    public AjaxResponse<?> updateLockStatus(@PathVariable Long id, @RequestBody Map<String, Boolean> payload) {
        userService.updateLockStatus(id, payload.get("locked"));
        return AjaxResponse.success(payload.get("locked") ? "锁定用户成功" : "解锁用户成功");
    }

    @Log(title = "启用/禁用用户", businessType = 2)
    @PutMapping("/{id}/enabled")
    @PreAuthorize("hasRole('ADMIN')")
    public AjaxResponse<?> updateEnabledStatus(@PathVariable Long id, @RequestBody Map<String, Boolean> payload) {
        userService.updateEnabledStatus(id, payload.get("enabled"));
        return AjaxResponse.success(payload.get("enabled") ? "启用用户成功" : "禁用用户成功");
    }

    @Log(title = "用户修改自己的密码", businessType = 2)
    @PutMapping("/change-password")
    public AjaxResponse<?> changePassword(@RequestBody Map<String, String> payload, @RequestParam String username) {
        User user = userService.findByUsername(username);
        if (user == null) {
            return AjaxResponse.error("用户不存在");
        }

        String oldPassword = payload.get("oldPassword");
        String newPassword = payload.get("newPassword");

        // 参数校验
        if (oldPassword == null || oldPassword.trim().isEmpty()) {
            return AjaxResponse.error("旧密码不能为空");
        }
        if (newPassword == null || newPassword.trim().isEmpty()) {
            return AjaxResponse.error("新密码不能为空");
        }

        try {
            userService.updatePassword(user.getId(), oldPassword, newPassword);
            return AjaxResponse.success("密码修改成功");
        } catch (RuntimeException e) {
            return AjaxResponse.error(e.getMessage());
        }
    }

    /**
     * 获取用户管理的建筑列表
     */
    @Log(title = "获取用户建筑列表", businessType = 0)
    @GetMapping("/{username}/buildings")
    @PreAuthorize("hasRole('ADMIN') or #username == authentication.name")
    public AjaxResponse<List<Building>> getUserBuildings(@PathVariable String username) {
        List<Building> buildings = userService.findUserBuildings(username);
        return AjaxResponse.success(buildings);
    }

    /**
     * 为用户分配建筑
     */
    @Log(title = "为用户分配建筑", businessType = 1)
    @PostMapping("/{username}/buildings")
    @PreAuthorize("hasRole('ADMIN')")
    public AjaxResponse<?> assignBuildingToUser(
            @PathVariable String username,
            @RequestBody Map<String, String> payload) {

        userService.assignBuildingToUser(username, payload.get("buildingCode"));
        clearUserBuildingsCache(username);
        return AjaxResponse.success("分配建筑成功");
    }

    /**
     * 为用户批量分配建筑
     */
    @Log(title = "为用户批量分配建筑", businessType = 1)
    @PostMapping("/{username}/buildings/batch")
    @PreAuthorize("hasRole('ADMIN')")
    public AjaxResponse<?> assignBuildingsToUser(
            @PathVariable String username,
            @RequestBody Map<String, List<String>> payload) {

        userService.assignBuildingsToUser(username, payload.get("buildingCodes"));
        clearUserBuildingsCache(username);
        return AjaxResponse.success("批量分配建筑成功");
    }

    /**
     * 移除用户的建筑
     */
    @Log(title = "移除用户的建筑", businessType = 3)
    @DeleteMapping("/{username}/buildings/{buildingCode}")
    @PreAuthorize("hasRole('ADMIN')")
    public AjaxResponse<?> removeBuildingFromUser(
            @PathVariable String username,
            @PathVariable String buildingCode) {

        userService.removeBuildingFromUser(username, buildingCode);
        clearUserBuildingsCache(username);
        return AjaxResponse.success("移除建筑成功");
    }

    /**
     * 设置用户的建筑（替换所有）
     */
    @Log(title = "设置用户的建筑", businessType = 2)
    @PutMapping("/{username}/buildings")
    @PreAuthorize("hasRole('ADMIN')")
    public AjaxResponse<?> setUserBuildings(
            @PathVariable String username,
            @RequestBody Map<String, List<String>> payload) {

        userService.setUserBuildings(username, payload.get("buildingCodes"));
        clearUserBuildingsCache(username);
        return AjaxResponse.success("设置用户建筑成功");
    }

    /**
     * 检查用户是否有权限管理指定建筑
     */
    @Log(title = "检查用户建筑权限", businessType = 0)
    @GetMapping("/{username}/buildings/{buildingCode}/permission")
    public AjaxResponse<Boolean> checkBuildingPermission(
            @PathVariable String username,
            @PathVariable String buildingCode) {

        boolean hasPermission = userService.hasPermissionToBuilding(username, buildingCode);
        return AjaxResponse.success(hasPermission);
    }

    /**
     * 获取用户操作日志列表
     */
    @Log(title = "查询用户操作日志", businessType = 0)
    @GetMapping("/{username}/logs")
    @PreAuthorize("hasRole('ADMIN') or #username == authentication.name")
    public AjaxResponse<?> getUserLogs(
            @PathVariable String username,
            @RequestParam(defaultValue = "1") Integer page,
            @RequestParam(defaultValue = "10") Integer pageSize,
            @RequestParam(required = false) String status,
            @RequestParam(required = false) String ipaddr,
            @RequestParam(required = false) String beginTime,
            @RequestParam(required = false) String endTime) {

        Map<String, Object> params = new HashMap<>();
        params.put("loginName", username);
        params.put("status", status);
        params.put("ipaddr", ipaddr);
        params.put("beginTime", beginTime);
        params.put("endTime", endTime);
        params.put("offset", (page - 1) * pageSize);
        params.put("pageSize", pageSize);

        List<LoginInfo> list = loginInfoService.selectLoginInfoList(params);
        long total = loginInfoService.count(params);

        Map<String, Object> data = new HashMap<>();
        data.put("rows", list);
        data.put("total", total);

        return AjaxResponse.success(data);
    }
}
